/*
 * =====================================================================================
 *
 *       Filename:  indexer.cpp
 *
 *    Description:  indexer source
 *
 *        Version:  1.0
 *       Revision:  none
 *       Compiler:  gcc
 *
 *         Author:  Chancey (CN), chanceycn@gmail.com
 *        Company:  
 *
 * =====================================================================================
 */
#include "indexer.h"

using namespace std;

sgIndexer::sgIndexer(char *path) : __delim(PINYIN_DELIM)
{
    sgDict *dictObj = new sgDict;
    __mapDict = dictObj->load(path);
    MYLOG_INFO << "load dict" ;
    delete dictObj;
}

sgIndexer::~sgIndexer()
{
}

void
sgIndexer::__pinyinIndexer(const char *pinyinChar, uint32_t pinyinLen, VECTOR_STRING &vecPinyin, uint8_t isJianPin = 0)
{
    string pinyin;
    VECTOR_STRING::iterator itPinyin, end;

    // 临时切割字符串
    char pinyinStr[pinyinLen+1];
    pinyinStr[pinyinLen] = '\0';

    if(vecPinyin.empty() == true) {
        strncpy(pinyinStr, pinyinChar, pinyinLen);
        char *tmp = strtok(pinyinStr, & this->__delim);
        while(tmp != NULL) {
            // 全部为汉字的 pinyin or py 的索引
            if(isJianPin == 1) {
                pinyin = string(tmp, 1);
            } else {
                pinyin = string(tmp);
            }
            vecPinyin.push_back(pinyin);

            tmp = strtok(NULL, & this->__delim);
        }
    }
    else {
        VECTOR_STRING vecNew;
        end = vecPinyin.end();
        for(itPinyin = vecPinyin.begin(); itPinyin != end;) {
            strncpy(pinyinStr, pinyinChar, pinyinLen);
            char *tmp = strtok(pinyinStr, & this->__delim);
            while(tmp != NULL) {
                // 全部为汉字的 pinyin or py 的索引
                if(isJianPin == 1) {
                    pinyin = string(tmp, 1) + *itPinyin;
                } else {
                    pinyin = string(tmp) + *itPinyin;
                }
                vecNew.push_back(pinyin);

                tmp = strtok(NULL, & this->__delim);
            }
            itPinyin++;
        }
        vecNew.swap(vecPinyin);
    }
}

bool
sgIndexer::indexer(uint8_t *str, uint32_t len, uint64_t value, MAP_VEC &mapIndex)
{
    int32_t i, key_start;
    MAP_DICT::iterator __mapIt;

    // 保存拼音索引(主要处理多音字组合)
    VECTOR_STRING vecPinyin, vecPy;

    for(i = len - 1; i >= 0; i--) {
        if(str[i] > 128)
        {
            // 源字符串的偏移量
            key_start = i - GBK_LEN + 1;
            if(key_start < 0) {
                continue;
            }

            char *key = (char *)str + key_start;
            i--;

            // 获得汉字的对应拼音
            string hzKey(key, 2);
            __mapIt = __mapDict.find(hzKey);
            if (__mapIt != __mapDict.end()) {
                //MYLOG_INFO << hzKey << " " << (__mapIt->second).c_str() << " " << (__mapIt->second).length();
                this->__pinyinIndexer((__mapIt->second).c_str(), (__mapIt->second).length(), vecPinyin);
                this->__pinyinIndexer((__mapIt->second).c_str(), (__mapIt->second).length(), vecPy, 1);
            }
        }
        else
        {
            // 源字符串的偏移量
            key_start = i;

            char s = tolower(str[i]);
            if(s >= 97 && s <= 122)
            {
                char str[] = {s,0};
                this->__pinyinIndexer(str, 1, vecPinyin);
                this->__pinyinIndexer(str, 1, vecPy, 1);
            }
        }
        // 汉字索引插入最终索引集
        string vecKey = string((char *)str + key_start);
        this->indexesInsert(vecKey, value, mapIndex);

        // 拼音索引插入最终索引集
        VECTOR_STRING::iterator vecIt;

        for(vecIt = vecPinyin.begin(); vecIt != vecPinyin.end();) {
            this->indexesInsert(*vecIt, value, mapIndex);
            vecIt++;
        }

        for(vecIt = vecPy.begin(); vecIt != vecPy.end();) {
            this->indexesInsert(*vecIt, value, mapIndex);
            vecIt++;
        }
    }

    return true;
}

bool sgIndexer::indexesInsert(string &key, uint64_t value, MAP_VEC &mapIndex)
{
    MAP_VEC::iterator it;

    it = mapIndex.find(key);
    if (it != mapIndex.end()) {
        (it->second).push_back(value);
        mapIndex[key] = it->second;
    } else {
        suggestion::VectorUid mapValue;
        mapValue.push_back(value);
        mapIndex.insert(make_pair(key, mapValue));
    }

    return true;
}
